#include "config.h"
namespace config
{
    const AliasedRequiredValue<std::string> trace_file = {"t", "trace_file", "trace file name"};
    const AliasedValue<uint64_t> run_cycle = {"c", "run_cycle", 10, "total run cycle"};
    const AliasedValue<uint64_t> run_inst = {"i", "run_inst", 10, "total run inst"};
    const Value<uint> srand_seed = {"srand_seed", 0, "seed for srand()"};
} // namespace config

#include "counter.h"
#include "OoO/core.h"
#include "inorder/core.h"


#define USE_OutOfOrderCore 1


#if ENABLE_COUNTER
Counter cycle("Cycle-global");
Counter run_time("Run-time");
#else
uint64_t cycle = 0;
uint64_t run_time = 0;
#endif
void sim_main(void)
{
    spdlog::set_level(spdlog::level::trace);
    SPDLOG_INFO("using trace file: {}", std::string(config::trace_file));
    init_trace(config::trace_file);
    SPDLOG_INFO("using srand seed: {}", config::srand_seed);
    srand(config::srand_seed);
    uint64_t inst_cnt;
#if USE_OutOfOrderCore
    OoOCore core;
    run_time = get_time_us();
    while (cycle < config::run_cycle && core.backend->inst_cnt < config::run_inst && !core.backend->sim_finish)
    {
        core.run();
        cycle++;
    }
    run_time = get_time_us() - run_time;
    inst_cnt = core.backend->inst_cnt;
    core.print_counter();
#else
    InorderCore core;

    run_time = get_time_us();
    while (cycle < config::run_cycle && core.pipeline.inst_cnt < config::run_inst && !core.pipeline.sim_finish)
    {
        core.run();
        cycle++;
    }
    run_time = get_time_us() - run_time;
    inst_cnt = core.pipeline.inst_cnt;
    core.print_counter();
#endif
    if (run_time > 0)
    {
        printf(COLOR("[Perf Model] ", GREEN) "simulation speed: %.02f MHz %.02f MIPS\n", (float)cycle / run_time, (float)inst_cnt / run_time);
    }
    Counter inst("Instructions");
    inst = inst_cnt;
    Counter::print_counters();
}